using com.shinian.fcg.fbs;
using GF;
using GF.Debug;
using GF.MonoBehavior.ActionSequenceSystem;
using GF.ResourcesLoad;
using System;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 特效管理器
/// </summary>
public class FxPlayerMgr : MonoSingleton<FxPlayerMgr>
{
    private Dictionary<string, LinkedList<CFx>> m_cacheFxs;
    LinkedList<CFx> m_playingFxs;
    LinkedList<CFx> m_uniqueFxs;

    Action fxPlayEndEvent;

    void Start()
    {
        m_cacheFxs = new Dictionary<string, LinkedList<CFx>>();
        m_playingFxs = new LinkedList<CFx>();
        m_uniqueFxs = new LinkedList<CFx>();
    }

    #region Public Function
    public IFx PlayFx(int id, Action func = null)
    {
        if (!StaticDataMgr.instance.FxDataCache.ContainsKey(id))
            return null;

        if (func != null)
            fxPlayEndEvent = func;
        CFx fx = null;
        var fxData = StaticDataMgr.instance.FxDataCache[id];
        if (!string.IsNullOrEmpty(fxData.Attach))
        {
            var parentObj = GameObject.Find(fxData.Attach);
            if (parentObj != null)
            {
                fx = PlayFx(fxData, parentObj) as CFx;
                if (fx == null)
                {
                    return null;
                }
                fx.FxDataInfo = fxData;
            }
        }
        else
        {
            Debugger.LogError(string.Format("ID:{0} 没有设置Attack节点 必须要设置父节点", fxData.Id));
        }
        return fx;
    }

    IFx PlayFx(FxData fxData, GameObject parent)
    {
        LinkedList<CFx> cacheFxs;
        if (m_cacheFxs.TryGetValue(fxData.Path, out cacheFxs))
        {
            if (cacheFxs.Count != 0)
            {
                CFx cachefx = null;
                foreach (var fxInList in cacheFxs)
                {
                    if (fxInList == null)
                        continue;
                    cachefx = fxInList;
                    break;
                }

                if (cachefx != null)
                {
                    cacheFxs.Remove(cachefx);
                    cachefx.Reset();
                    cachefx.SetParent(parent);
                    cachefx.SetRotation(Quaternion.LookRotation(Vector3.forward));
                    cachefx.SetActive(true);
                    m_playingFxs.AddLast(cachefx);
                    cachefx.IsRecycled = false;
                    return cachefx;
                }
            }
        }
#if LCS
        GameObject fxObj = AppFacade.Instance.ResMgr.Load(fxData.Path, typeof(GameObject)) as GameObject;
#else
        GameObject fxObj = CResourceManager.Load<GameObject>(fxData.Path);
#endif

        if (fxObj == null)
        {
            Debug.LogError("没有找到特效:" + fxData.Path);
            return null;
        }
        var obj = GameObject.Instantiate(fxObj);
        CFx fx = obj.AddComponent<CFx>();
        if (fx != null)
        {
            fx.Init(obj.transform);
            fx.SetParent(parent);

            if (fxData.RotateLength == 3)
                fx.SetLocalRotation(Quaternion.Euler(fxData.Rotate(0), fxData.Rotate(1), fxData.Rotate(2)));
            else
                fx.SetLocalRotation(Quaternion.Euler(Vector3.zero));
            if (fxData.OffsetLength == 3)
                fx.SetLocalPosition(new Vector3(fxData.Offset(0), fxData.Offset(1), fxData.Offset(2)));
            else
                fx.SetLocalPosition(Vector3.zero);
            if (fxData.Scale > 0)
                fx.SetScale(fxData.Scale);
            m_playingFxs.AddLast(fx);

            if (fxData.LoopType == 0 && fxData.Duration > 0)  //不循环
            {
                this.Delayer(fxData.Duration / 1000, () =>
                {
                    DestroyFx(fx);
                    if (fxPlayEndEvent != null)
                    {
                        fxPlayEndEvent();
                        fxPlayEndEvent = null;
                    }
                });
            }
        }
        fx.IsRecycled = false;
        return fx;
    }

    public void DeleteAllFx()
    {
        foreach (var fxList in m_cacheFxs)
        {
            foreach (var fx in fxList.Value)
            {
                GameObject.Destroy(fx.gameObject);
            }
            fxList.Value.Clear();
        }
        m_playingFxs.Clear();
    }

    public void DestroyFx(IFx ifx)
    {
        if (ifx == null)
            return;
        CFx fx = ifx as CFx;
        if (fx == null)
            return;
        LinkedList<CFx> cachedFxs;
        if (m_cacheFxs.TryGetValue(fx.GetPath(), out cachedFxs))
        {
            cachedFxs.Remove(fx);
            m_playingFxs.Remove(fx);
        }
        GameObject.Destroy(fx.transform.gameObject);
        fx = null;
    }

    public void RecycleFx(IFx ifx)
    {
        if (ifx == null)
            return;
        CFx fx = ifx as CFx;
        if (fx == null)
            return;
        fx.IsRecycled = true;

        if (string.IsNullOrEmpty(fx.GetPath()))
        {
            GameObject.Destroy(fx.gameObject);
            return;
        }

        LinkedList<CFx> cachedFxs;
        if (m_cacheFxs.TryGetValue(fx.GetPath(), out cachedFxs))
        {
            cachedFxs.AddLast(fx);
            m_playingFxs.Remove(fx);
        }
        else
        {
            cachedFxs = new LinkedList<CFx>();
            m_cacheFxs.Add(fx.GetPath(), cachedFxs);
        }

        fx.SetActive(false);
        fx.SetOwner(null);
        fx.transform.localScale = Vector3.one;
    }
    #endregion
}
